<?php

namespace Cck\ArticlesSystem\Http\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\SoftDeletes;

/**
 * 文章
 * @property string $title
 * @property integer $creator_id
 * @property integer $category_id
 * @property integer $keyword_id
 * @property string $catalogue
 * @property string $cover
 * @property-read string $cover_url
 * @property boolean $recommend
 * @property string $seo_title
 * @property string $seo_keywords
 * @property string $seo_description
 * @property integer $views_count
 * @property integer $verify_status
 * @property string $slug
 * 
 * @method Builder withoutPublished()
 * 
 * @property-read Category $category
 * @property-read User $creator
 * @property-read Keyword $keyword
 * @property-read Tag[]|Collection $tags
 */
class Article extends Model
{
    // use SoftDeletes;

    protected $table = 'articles';

    const VERIFY_STATUS_PENDING = 0;
    const VERIFY_STATUS_AGREED = 1;
    const VERIFY_STATUS_REFUSED = 2;

    protected $fillable = [
        'title', 'creator_id', 'category_id', 'keyword_id', 'catalogue', 'cover', 'recommend', 'seo_title', 'seo_keywords', 'seo_description', 'views_count', 'verify_status', 'slug', 'content', 'published_at'
    ];

    protected $dates = [
        'deleted_at', 'published_at'
    ];

    protected $casts = [
        'creator_id' => 'integer',
        'category_id' => 'integer',
        'keyword_id' => 'integer',
        'recommend' => 'boolean',
        'views_count' => 'integer',
        'verify_status' => 'integer'
    ];

    protected static function boot()
    {
        parent::boot();

        static::addGlobalScope('published', function ($q) {
            $q->where('published_at', '>=', now())->where('verify_status', self::VERIFY_STATUS_AGREED);
        });

        static::created(function (self $article) {
            if ($article->keyword_id) {
                Keyword::query()->where('id', $article->keyword_id)->update(['used_at' => now()]);
            }
        });

        static::creating(function (self $article) {

            if (settings('enable_article_audit', false)) {
                $article->verify_status = self::VERIFY_STATUS_PENDING;
            } else {
                $article->verify_status = self::VERIFY_STATUS_AGREED;
            }

            if (!$article->catalogue || !$article->slug) {
                if (!$article->slug) {
                    $setting = settings('article_slug_length', ['min' => 3, 'max' => 5]);
                    [$min, $max] = [$setting['min'], $setting['max']];

                    switch (strtolower(settings('article_slug_generate_rule', 'id'))) {
                        case 'id':
                            $article->slug = self::query()->max('id') + 1;
                        case 'random_letters_and_numbers':
                            $article->slug = randomNumbersAndLetters($min, $max);
                        case 'random_numbers':
                            $article->slug = randomNumbers($min, $max);
                        case 'random_letters':
                        default:
                            $article->slug = randomLetters($min, $max);
                    }
                }

                if (!$article->catalogue) {
                    $setting = settings('article_catalogue_length', ['min' => 3, 'max' => 5]);

                    [$min, $max] = [$setting['min'], $setting['max']];

                    switch (strtolower(settings('article_catalogue_generate_rule', 'source_catalogue'))) {
                        case 'source_catalogue':
                            /** @var Category $category */
                            $category = Category::query()->findOrFail($article->category_id);
                            $article->catalogue = $category->slug;
                            break;
                        case 'random_numbers':
                            $article->catalogue = randomNumbers($min, $max);
                            break;
                        case 'random_letters':
                            $article->catalogue = randomLetters($min, $max);
                            break;
                        case 'random_letters_and_numbers':
                            $article->catalogue = randomNumbersAndLetters($min, $max);
                            break;
                        case 'root_catalogue':
                        default:
                            $article->catalogue = '';
                            break;
                    }
                }
            }
        });
    }

    public static function getVerifyStatusOptions(): array
    {
        return [
            self::VERIFY_STATUS_PENDING => '等待审核',
            self::VERIFY_STATUS_AGREED => '通过',
            self::VERIFY_STATUS_REFUSED => '拒绝'
        ];
    }

    public function scopeWithoutPublished($q)
    {
        /** @var Builder $q */
        return $q->withoutGlobalScope('published');
    }

    public function creator()
    {
        return $this->belongsTo(User::class, 'creator_id', 'id');
    }

    public function category()
    {
        return $this->belongsTo(Category::class, 'category_id', 'id');
    }

    public function tags()
    {
        return $this->morphToMany(Tag::class, 'taggable', 'taggables')->using(Taggable::class);
    }

    public function taggables()
    {
        return $this->morphMany(Taggable::class, 'taggable', 'taggable_type', 'taggable_id', 'id');
    }

    public function keyword()
    {
        return $this->belongsTo(Keyword::class, 'keyword_id', 'id');
    }

    public function getUrlAttribute()
    {
        if (!isset($this->attributes['slug']) || !isset($this->attributes['catalogue'])) {
            return '';
        }
    }
}
